/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * DragBarBG.java
 *
 * Created on May 14, 2009, 8:43:02 AM
 */
package DragBarPanelPackage;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.util.Vector;
import javax.swing.JPanel;

/**
 * This class draws the background for a dragbar.  Basically it'll make those
 * lines that the button sliders will align to.
 * @author Heather
 */
public class DragBarBG extends JPanel
{

  /** Creates new form DragBarBG */
  public DragBarBG()
  {
    initComponents();
  }

  /** This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  @SuppressWarnings("unchecked")
  // <editor-fold defaultstate="collapsed" desc="Generated Code">
  private void initComponents()
  {
  }// </editor-fold>

  // Variables declaration - do not modify
  // End of variables declaration
  private static final int DEFAULT_HORIZONTAL_HEIGHT = 4;
  private static final int DEFAULT_VERTICAL_WIDTH = 6;
  // offscreen buffer for painting
  private Image buffer;
  // graphics for painting
  private Graphics bufferG;
  private Vector<Point> verticalLocations = new Vector<Point>();
  private Vector<Boolean> hasTriangleVector = new Vector<Boolean>();
  private Rectangle horizontalBar = new Rectangle();
  private static final int DEFAULT_MAIN_COLOR_STRENGTH = 60;
  private static final int DEFAULT_SUPPORT_COLOR_STRENGTH = 80;
  private static final Color DEFAULT_HORIZONTAL_COLOR = new Color(170, 170, 255);
  private Color horizontalColor = DEFAULT_HORIZONTAL_COLOR;
  private static final Color DEFAULT_VERTICAL_POSITIVE_COLOR = new Color(0, DEFAULT_MAIN_COLOR_STRENGTH, 0);
  private Color verticalPositiveColor = DEFAULT_VERTICAL_POSITIVE_COLOR;
  private static final Color DEFAULT_VERTICAL_NEGATIVE_COLOR = new Color(DEFAULT_MAIN_COLOR_STRENGTH, 0, 0);
  private Color verticalNegativeColor = DEFAULT_VERTICAL_NEGATIVE_COLOR;
  private static final int DEFAULT_TRIANGLE_BASE_WIDTH = 30;
  private static final int DEFAULT_TRIANGLE_HEIGHT = 45;
  // this is used to scale the coloring according to the size of the maximum scale in
  // the dragbarpanel
  private int maxColorHeight = 100;

  //returns the value of the upper right corner where verticalPosition is the
  // to middle pt.
  private Point findCorner(Point verticalPosition, int height)
  {
    int x = verticalPosition.x - DEFAULT_VERTICAL_WIDTH;
    int y = verticalPosition.y;

    return new Point(x, y);
  }

  // draws all lines
  public void drawLines()
  {
    int halfHeight = getSize().height / 2;

    // clear the window
    if (bufferG == null)
    {
      setupBuffers();
    }
    bufferG.setColor(Color.white);
    bufferG.fillRect(0, 0, getSize().width, getSize().height);

    Graphics windowG = getGraphics();
    int horizontalX = 0;
    int horizontalY = halfHeight - (DEFAULT_HORIZONTAL_HEIGHT / 2);

    // draw horizontal line
    bufferG.setColor(horizontalColor);
    windowG.setColor(horizontalColor);
    bufferG.fillRect(horizontalX, horizontalY, getSize().width, DEFAULT_HORIZONTAL_HEIGHT);
    windowG.fillRect(horizontalX, horizontalY, getSize().width, DEFAULT_HORIZONTAL_HEIGHT);

    for (int i = 0; i < verticalLocations.size(); i++)
    {
      Point p = verticalLocations.get(i);
      int height = Math.abs(halfHeight - p.y);

      int mainColorStrength = (int) (((double) height / maxColorHeight) * 255);
      if (mainColorStrength > 255)
      {
        mainColorStrength = 255;
      }

      int supportColorStrength = (int) (DEFAULT_SUPPORT_COLOR_STRENGTH - ((double) height / maxColorHeight) * 255);
      if (supportColorStrength < 0)
      {
        supportColorStrength = 0;
      }

      // if the line is positive (b/c 0 is the top of the screen)
      if (halfHeight > p.y)
      {
        bufferG.setColor(new Color(supportColorStrength, mainColorStrength, supportColorStrength));
        windowG.setColor(new Color(supportColorStrength, mainColorStrength, supportColorStrength));
        bufferG.fillRect(p.x - DEFAULT_VERTICAL_WIDTH, p.y, DEFAULT_VERTICAL_WIDTH, height);
        windowG.fillRect(p.x - DEFAULT_VERTICAL_WIDTH, p.y, DEFAULT_VERTICAL_WIDTH, height);
        // if there is a triangle associated w/ this line, draw it
        if (hasTriangleVector.get(i))
        {
          int centerX = p.x - DEFAULT_VERTICAL_WIDTH / 2;
          int centerY = p.y;
          bufferG.fillPolygon(getFillPolygon(new Point(centerX, centerY), true));
          windowG.fillPolygon(getFillPolygon(new Point(centerX, centerY), true));
        }
      }
      else // else if the line is negative.
      {
        bufferG.setColor(new Color(mainColorStrength, supportColorStrength, supportColorStrength));
        windowG.setColor(new Color(mainColorStrength, supportColorStrength, supportColorStrength));
        bufferG.fillRect(p.x - DEFAULT_VERTICAL_WIDTH, halfHeight, DEFAULT_VERTICAL_WIDTH, height);
        windowG.fillRect(p.x - DEFAULT_VERTICAL_WIDTH, halfHeight, DEFAULT_VERTICAL_WIDTH, height);
        // if there is a triangle associated w/ this line, draw it
        if (hasTriangleVector.get(i))
        {
          int centerX = p.x - DEFAULT_VERTICAL_WIDTH / 2;
          int centerY = p.y;
          bufferG.fillPolygon(getFillPolygon(new Point(centerX, centerY), false));
          windowG.fillPolygon(getFillPolygon(new Point(centerX, centerY), false));
        }
      }
    }
  }

  // updates 1 line.  newHeight can be negative to go in the negative
  // direction
  public void updateLineX(int index, Point newPt)
  {
    verticalLocations.set(index, newPt);
  }

  public void addLine(Point location)
  {
    verticalLocations.add(location);
    hasTriangleVector.add(false);
  }

  public void setTriangleVector(int index, boolean bool)
  {
    if ((index < hasTriangleVector.size()) && (index > -1))
    {
      hasTriangleVector.set(index, bool);
    }
  }

  public void paint(Graphics g)
  {
    setupBuffers();
    g.drawImage(buffer, 0, 0, this);
    drawLines();
  }

  private void setupBuffers()
  {
    // This creates the buffer
    if ((buffer == null) || (bufferG == null))
    {
      int xBound = getSize().width;
      int yBound = getSize().height;

      buffer = this.createImage(xBound, yBound);
      bufferG = buffer.getGraphics();
      bufferG.setColor(Color.white);
      bufferG.fillRect(0, 0, xBound, yBound);
    }
  }

  public void clear()
  {
    int xBound = getSize().width;
    int yBound = getSize().height;

    Graphics windowG = getGraphics();
    bufferG.setColor(Color.WHITE);
    windowG.setColor(Color.WHITE);
    bufferG.fillRect(0, 0, xBound, yBound);
    windowG.fillRect(0, 0, xBound, yBound);

    verticalLocations.clear();
    drawLines();
  }

  public void setMaxColorHeight(int newMax)
  {
    maxColorHeight = newMax;
  }

  public void setSize(Dimension d)
  {
    super.setSize(d);
    buffer = null;
  }

  public void setSize(int x, int y)
  {
    super.setSize(x, y);
    buffer = null;
  }

  // this will return a triangle where the center of the base
  // is defined by center.  The boolean is used to flag whether
  // the triangle points up or down.  True is up, false is down.
  private Polygon getFillPolygon(Point center, boolean isPointedUp)
  {
    int[] newXCoords = new int[3];
    int[] newYCoords = new int[3];
    int totalP = 3;

    int halfBase = DEFAULT_TRIANGLE_BASE_WIDTH / 2;
    // left
    newXCoords[0] = center.x - halfBase;
    newYCoords[0] = center.y;
    // right
    newXCoords[1] = center.x + halfBase;
    newYCoords[1] = center.y;
    // top
    newXCoords[2] = center.x;

    Point top;
    if (isPointedUp)
    {
      newYCoords[2] = center.y - DEFAULT_TRIANGLE_HEIGHT;
    }
    else
    {
      newYCoords[2] = center.y + DEFAULT_TRIANGLE_HEIGHT;
    }

    return new Polygon(newXCoords, newYCoords, totalP);
  }
}

